/*
 * Eugen Stoian <stoian.e@gmail.com> 2010
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "Interval.h"
#include <cfloat>
#include <cmath>
#include <QStringList>
#include <MathParser.h>

Interval::Interval(double inf, double sup, bool leftClosed, bool rightClosed)
        :_inf(inf),_sup(sup),_leftClosed(leftClosed),_rightClosed(rightClosed){
}

Interval::Interval(const Interval& interval){
    this->_inf = interval._inf;
    this->_sup = interval._sup;
    this->_leftClosed = interval._leftClosed;
    this->_rightClosed = interval._rightClosed;
}

Interval& Interval::operator=(const Interval& interval){
    if(this!=&interval){
        this->_inf = interval._inf;
        this->_sup = interval._sup;
        this->_leftClosed = interval._leftClosed;
        this->_rightClosed = interval._rightClosed;
    }
    return *this;
}

Interval::Interval(const QString& s){
    QString str = s.trimmed();
    if(str.contains('(')){
        str.remove('(');
        _leftClosed = false;
    }
    else {
        str.remove('[');
        _leftClosed = true;
    }
    if(str.contains(')')){
        str.remove(')');
        _rightClosed = false;
    }
    else {
        str.remove(']');
        _rightClosed = true;
    }
    QStringList list = str.split(',');
    SmartPtr<ExpressionTreeNode> node;
    QString code = "tmp[x] = "+ list.front().trimmed()+".";
    MathParser::parse(code);
    node = MathParser::getTree("tmp[]");
    if(node)
        _inf=node->eval();
    else
        _inf = 0.0;

    MathParser::removeFun("tmp[]");
    code = "tmp[x] = "+ list.back().trimmed()+".";
    MathParser::parse(code);
    node = MathParser::getTree("tmp[]");
    if(node)
        _sup=node->eval();
    else
        _sup = 0.0;

    MathParser::removeFun("tmp[]");
}

Interval::operator QString() const {
    QString left = _leftClosed?"[":"(";
    QString right = _rightClosed?"]":")";
    return left+QString::number(_inf)+","+QString::number(_sup)+right;
}

double Interval::first() const {
    if(_leftClosed)
        return _inf;
    else{
        if(fabs(_inf)<1.0)
            return _inf+DBL_MIN;
        return _inf+DBL_EPSILON;
    }
}
double Interval::last() const {
    if(_rightClosed)
        return _sup;
    else{
        if(fabs(_sup)<1.0)
            return _sup-DBL_MIN;
        return _sup-DBL_EPSILON;
    }
}

bool Interval::contains(double value) const {
    if((_inf < value) && (value < _sup))
        return true;
    if(_leftClosed && (value == _inf))
        return true;
    if(_rightClosed && (value == _sup))
        return true;
    return false;
}
